package cn.wuxing.mediation.Filter;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;

/**
 * @author gepanyang
 * @description: 响应日志输出过滤器
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered{
    @Override
    public int getOrder() {
        //-1 is response write filter, must be called before that
        return -2;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取response的 返回数据
        ServerHttpResponse originalResponse = exchange.getResponse();
        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
//        StringBuffer responseBuffer =new StringBuffer();
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            @NotNull
            @Override
            public Mono<Void> writeWith(@NotNull Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = Flux.from(body);

                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {

                        StringBuilder responseBuffer = new StringBuilder(1024);
                        dataBuffers.forEach(dataBuffer -> {
                            try {
                                byte[] content = new byte[dataBuffer.readableByteCount()];
                                dataBuffer.read(content);
                                DataBufferUtils.release(dataBuffer);
                                String data = new String(content, StandardCharsets.UTF_8);
                                responseBuffer.append(data);
                            } catch (Exception e) {
                                log.error("rsp log, list add error", e);
                            }
                        });

                        String responseStr = responseBuffer.toString();
                        String canstr="";
                        if(responseStr.length()>=400){
                            canstr="...此次省去N个结果....";
                        }
                        try {
                            String requestId = responseStr.substring(responseStr.indexOf("RequestId") + 3, responseStr.indexOf("RequestId") + 400) + canstr;
                            log.info("{} 响应结果，code:{},RequestId：{}", exchange.getAttributes().get("requestId"), getStatusCode(), requestId);
                            log.info("{} --------------------- 请求结束 ------------------------", exchange.getAttributes().get("requestId"));
                        }catch (Exception e){
                            log.info("{} 响应结果： ", "接口非正常解析或者接口程序出错啦！！！");
                            log.info("{} --------------------- 请求结束 ------------------------");
                        }

                        String result = responseBuffer.toString();
                        getDelegate().getHeaders().setContentLength(result.getBytes().length);
                        return bufferFactory.wrap(result.getBytes());
                    }));
                }
                return super.writeWith(body);
            }
        };
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }
}
